#include <iostream>
#include <cstdio> // perror
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <string>
#include <cstdlib>

using namespace std;

// static void Usage(const string &proc)
// {
//     cout << "\nUsage: " << proc << " pid signo\n" << endl;
// }

// void catchSig(int signo)
// {
//     cout << "获取到一个信号，信号编号是： " << signo << endl;
//     exit(1);
// }

// int cnt = 0; // 设置成全局变量

// void catchSig(int signo)
// {
//     cout << "获取到一个信号，信号编号是： "  << cnt << endl;
//    // exit(1);
//    alarm(1); //这样能实现每隔一秒打印一次   alarm(0); // 取消闹钟
// }


void catchSig(int signo)
{
    cout << "获取到一个信号，信号编号是： "  << signo << endl; // 信号捕捉
}

// ./myprocess pid signo
int main(int argc , char *argv[])
{
    for(int signo = 1; signo <= 31; signo++)
    {
        signal(signo, catchSig);
    }

    while(true) 
    {
        cout << " 我在运行: " << getpid() << endl;
        sleep(1);
    }

    // 核心转储
    // while(true)
    // {
    //     int a[10];
    //     // a[10000] = 20;
    // }

//     // 4. 软件条件 -- “闹钟” 其实就是用软件实现的
 
//     // 统计1s左右，我们的计算机能够将数据累计多少次
//     signal(SIGALRM,catchSig);

//     alarm(1);

//    // int cnt = 0;

//     while(true)
//     {
//        // cout << "cnt: "<< cnt++ <<  endl;
//        cnt++;
//     }


    // // 3. 产生信号的的方式 ： 硬件异常产生信号
    // // 信号产生，不一定非得用户显示的发送！

    // // signal(SIGFPE,catchSig);

    // signal(11,catchSig); //这个对应野指针
    // // 当程序接收到信号 11（SIGSEGV，即段错误）时，调用 catchSig 函数来处理这个信号

    // while(true)
    // {
    //     //cout << "我在运行中...." << endl;
    //     // int a = 10;
    //     // // 收到信号，不一定会引起进程退出 -- 进程没有退出，有可能还会被调到 
    //     // // --- CPU内部寄存器只有一份，但是寄存器中的内容，属于当前进程的上下文！
    //     // // 你有没有能力或者动作去修正这个问题呢？ -- 没有
    //     // // 当进程被切换的时候，就有无数次状态寄存器被保存和恢复的过程
    //     // // 所以每一次恢复的时候，就让OS识别到了CPU内部的状态寄存器中的溢出标志位是1

    //     // // 如何证明
    //     // // OS如何得知应该给当前进程发送8号信号的 --- OS怎么知道我除0了？ 因为CPU会异常，标志位会溢出
    //     // a /= 0; // 为什么除0会终止进程？当前进程会受到来自OS系统的信号（告知）,SIGFPE
    //     //sleep(1);

    //     cout << "我在运行中...." << endl;
    //     sleep(1);
    //     int *p = nullptr;
    //     p = nullptr; // 这种情况是可以的
    //     // OS怎么知道我野指针了呢
    //     *p = 100; // 野指针

    // }

    // 2. 系统调用向目标进程发送信号
    // kill() 可以向任意进程 发送 任意信号
    // raise() 给自己 发送 任意信号 kill（getpid(), 任意信号）
    // abort() 给自己 发送 指定的信号 6号信号 SIGABRT , kill（getpid(), SIGABRT）
    // 关于信号处理行为的理解：在很多情况下，进程收到大部分的信号，默认处理动作都是终止进程
    // 信号的意义：信号的不同，代表不同的事件，但是对事件发生之后的处理动作可以一样！

    // int cnt = 0;
    // while(cnt <= 10)
    // {
    //    // printf("cnt: %d\n",cnt++);
    //     printf("cnt: %d, pid: %d\n",cnt++, getpid());

    //     sleep(1);


    //     // if(cnt == 5)
    //     // {
    //     //    // raise(9);
    //     //     abort();
    //     // }
    // }

    // if( argc != 3)
    // {
    //     Usage(argv[0]);
    //     exit(1);
    // }

    // pid_t pid = atoi(argv[1]); // atoi 将字符串转化成数字
    // int signo = atoi(argv[2]);
    // int n = kill(pid , signo);

    // if( n != 0) // n == 0发送成功
    // {
    //     perror("kill");
    // }

    // 1. 通过键盘发送信号
    // while(true)
    // {
    //     cout << "hello world" << endl;
    //     sleep(1);
    // }
    return 0;
}